package cn.dakaqi.services.impl;

import cn.dakaqi.dao.GroupRecruitDao;
import cn.dakaqi.entities.GroupRecruit;
import cn.dakaqi.entities.IndexData;
import cn.dakaqi.entities.user.Volunteer;
import cn.dakaqi.services.GroupRecruitService;
import cn.dakaqi.services.GroupService;
import cn.dakaqi.services.IndexDataService;
import cn.dakaqi.services.user.VolunteerService;
import cn.dakaqi.utils.Clock;
import cn.dakaqi.utils.DKQConstant;
import cn.dakaqi.utils.exception.ServiceRuntimeException;
import com.alibaba.fastjson.JSON;
import com.alibaba.fastjson.JSONObject;
import com.google.common.collect.Lists;
import com.google.common.collect.Maps;
import org.apache.commons.lang3.StringUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.domain.Page;
import org.springframework.data.domain.PageRequest;
import org.springframework.data.domain.Sort;
import org.springframework.data.jpa.domain.Specification;
import org.springframework.stereotype.Component;
import org.springframework.transaction.annotation.Transactional;
import org.springside.modules.persistence.DynamicSpecifications;
import org.springside.modules.persistence.SearchFilter;

import javax.persistence.criteria.*;
import java.text.ParseException;
import java.text.SimpleDateFormat;
import java.util.*;

/**
 * Created by chunyang on 2016/4/22.
 */
@Component(value = "groupRecruitService")
@Transactional
public class GroupRecruitServiceImpl implements GroupRecruitService
{
    @Autowired
    GroupRecruitDao groupRecruitDao;
    @Autowired
    GroupService groupService;
    @Autowired
    VolunteerService volunteerService;
    @Autowired
    IndexDataService indexDataService;

    @Override
    public void create(String param) throws ServiceRuntimeException
    {
        JSONObject jsonObject = JSON.parseObject(param);

            String groupCode = jsonObject.getString("groupCode");
            String memberCode = jsonObject.getString("memberCode");
            String title = jsonObject.getString("title");
            String demo = jsonObject.getString("demo");
            String stopApplyTime = jsonObject.getString("stopApplyTime");
            int needs = jsonObject.getInteger("needs");
            String job = jsonObject.getString("job");
            String skill = jsonObject.getString("skill");
            String serviceField = jsonObject.getString("serviceField");
            String img = jsonObject.getString("img");
            String question = jsonObject.getString("question");
            Date createTime = Clock.DEFAULT.getCurrentDate();

            Volunteer volunteer = this.volunteerService.findByMemberCode(memberCode);
            GroupRecruit groupRecruit = new GroupRecruit();
            groupRecruit.setGroup(this.groupService.findByGroupCode(groupCode));
            groupRecruit.setVolunteer(volunteer);
            groupRecruit.setTitle(title);
            groupRecruit.setDemo(demo);
            groupRecruit.setNeeds(needs);
            groupRecruit.setJob(job);
            groupRecruit.setSkill(skill);
            groupRecruit.setServiceField(serviceField);
            groupRecruit.setImg(img);
            groupRecruit.setStatus(DKQConstant.PROCEED_START);
            groupRecruit.setCreateTime(createTime);
            groupRecruit.setLinkman(volunteer.getRealName());
            groupRecruit.setPhone(volunteer.getMobile());
            groupRecruit.setStopApplyTime(stopApplyTime);
            groupRecruit.setQuestion(question);
            this.save(groupRecruit);
    }

    @Override
    public void save(GroupRecruit groupRecruit) throws ServiceRuntimeException
    {
        //如果当前社团的招募未结束，则不可以发布新的招募
        GroupRecruit temp = findNotEnd(groupRecruit.getGroup().getGroupCode());
        if(null != temp)
            throw new ServiceRuntimeException("当前社团有未结束的社团招募,暂时不可以发布新的招募");

        groupRecruitDao.save(groupRecruit);

        //将活动招募放入首页自定义的容器中
        IndexData indexData = new IndexData();
        indexData.setType("GroupRecruit");
        indexData.setCreateTime(Clock.DEFAULT.getCurrentDate());
        indexData.setDisplay(DKQConstant.DISPLAY_YES);
        indexData.setGroupRecruit(groupRecruit);
        indexData.setDelStatus(DKQConstant.DEL_NO);
        indexData.setStopStatus(DKQConstant.PROCEED_START);
        indexData.setTop(DKQConstant.TOP_NO);
        indexData.setSkill(groupRecruit.getSkill());
        indexData.setJob(groupRecruit.getJob());
        indexData.setServiceField(groupRecruit.getServiceField());
        indexData.setCity(groupRecruit.getGroup().getCity());
        SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");
        try
        {
            indexData.setStopTime(sdf.parse(groupRecruit.getStopApplyTime() + ":00"));
        } catch (ParseException e)
        {
            e.printStackTrace();
        }
        this.indexDataService.save(indexData);
    }

    @Override
    public void update(GroupRecruit groupRecruit) throws ServiceRuntimeException
    {
        this.groupRecruitDao.save(groupRecruit);
    }

    @Override
    public GroupRecruit findOne(Long id) throws ServiceRuntimeException
    {
        GroupRecruit groupRecruit = groupRecruitDao.findOne(id);
        if(null != groupRecruit)
        {
            groupRecruit.setBrowses(groupRecruit.getBrowses()+1);
            this.groupRecruitDao.save(groupRecruit);
        }
        return groupRecruit;
    }

    @Override
    public GroupRecruit findNotEnd(String groupCode) throws ServiceRuntimeException
    {
        Map<String, SearchFilter> filters = Maps.newHashMap();
        filters.put("group.groupCode", new SearchFilter("group.groupCode", SearchFilter.Operator.EQ, groupCode));
        filters.put("status", new SearchFilter("status", SearchFilter.Operator.EQ, DKQConstant.PROCEED_START));
        filters.put("delStatus", new SearchFilter("delStatus", SearchFilter.Operator.EQ, DKQConstant.DEL_NO));
        Specification<GroupRecruit> spec = DynamicSpecifications.bySearchFilter(filters.values(), GroupRecruit.class);
        List<GroupRecruit> list =  this.groupRecruitDao.findAll(spec);
        if(null != list && list.size()>0)
            return list.get(0);

        return null;
    }

    @Override
    public List<GroupRecruit> findByGroup(Long groupId) throws ServiceRuntimeException
    {
        Map<String, SearchFilter> filters = Maps.newHashMap();
        filters.put("group.id", new SearchFilter("group.id", SearchFilter.Operator.EQ, groupId));
        filters.put("delStatus", new SearchFilter("delStatus", SearchFilter.Operator.EQ, DKQConstant.DEL_NO));
        Specification<GroupRecruit> spec = DynamicSpecifications.bySearchFilter(filters.values(), GroupRecruit.class);
        return this.groupRecruitDao.findAll(spec);
    }

    @Override
    public List<GroupRecruit> findByGroupCode(String groupCode) throws ServiceRuntimeException
    {
        //Map<String,Object> map = new HashMap<String, Object>();
        //map.put("LIKE_NAME",name);
        //Map<String, SearchFilter> filters = SearchFilter.parse(map);

        Map<String, SearchFilter> filters = Maps.newHashMap();
        filters.put("group.groupCode", new SearchFilter("group.groupCode", SearchFilter.Operator.EQ, groupCode));
        filters.put("delStatus", new SearchFilter("delStatus", SearchFilter.Operator.EQ, DKQConstant.DEL_NO));
        Specification<GroupRecruit> spec = DynamicSpecifications.bySearchFilter(filters.values(), GroupRecruit.class);
        return this.groupRecruitDao.findAll(spec);
    }

    @Override
    public Page<GroupRecruit> findByVolunteer(String memberCode,int pageNumber) throws ServiceRuntimeException
    {
        Sort sort = new Sort(Sort.Direction.DESC, "createTime");
        PageRequest pageRequest = new PageRequest(pageNumber - 1, 20, sort);
        Map<String, SearchFilter> filters = Maps.newHashMap();
        filters.put("volunteer.memberCode", new SearchFilter("volunteer.memberCode", SearchFilter.Operator.EQ, memberCode));
        filters.put("delStatus", new SearchFilter("delStatus", SearchFilter.Operator.EQ, DKQConstant.DEL_NO));
        Specification<GroupRecruit> spec = DynamicSpecifications.bySearchFilter(filters.values(), GroupRecruit.class);
        return this.groupRecruitDao.findAll(spec,pageRequest);
    }

    @Override
    public Page<GroupRecruit> findByGroupCode(String groupCode, int pageNumber) throws ServiceRuntimeException
    {
        Sort sort = new Sort(Sort.Direction.DESC, "createTime");
        PageRequest pageRequest = new PageRequest(pageNumber - 1, 20, sort);
        Map<String, SearchFilter> filters = Maps.newHashMap();
        filters.put("group.groupCode", new SearchFilter("group.groupCode", SearchFilter.Operator.EQ, groupCode));
        filters.put("delStatus", new SearchFilter("delStatus", SearchFilter.Operator.EQ, DKQConstant.DEL_NO));
        Specification<GroupRecruit> spec = DynamicSpecifications.bySearchFilter(filters.values(), GroupRecruit.class);
        return this.groupRecruitDao.findAll(spec,pageRequest);
    }

    @Override
    public Page<GroupRecruit> findByTitle(String groupCode, String key)
    {
        Sort sort = new Sort(Sort.Direction.DESC, "createTime");
        PageRequest pageRequest = new PageRequest(0, 200, sort);
        Map<String, SearchFilter> filters = Maps.newHashMap();
        filters.put("group.groupCode", new SearchFilter("group.groupCode", SearchFilter.Operator.EQ, groupCode));
        filters.put("delStatus", new SearchFilter("delStatus", SearchFilter.Operator.EQ, DKQConstant.DEL_NO));
        filters.put("title", new SearchFilter("title", SearchFilter.Operator.LIKE, key));
        Specification<GroupRecruit> spec = DynamicSpecifications.bySearchFilter(filters.values(), GroupRecruit.class);
        return this.groupRecruitDao.findAll(spec,pageRequest);
    }

    @Override
    public GroupRecruit findLastByGroupCode(String groupCode,int status) throws ServiceRuntimeException
    {
        Map<String, SearchFilter> filters = Maps.newHashMap();
        filters.put("group.groupCode", new SearchFilter("group.groupCode", SearchFilter.Operator.EQ, groupCode));
        filters.put("delStatus", new SearchFilter("delStatus", SearchFilter.Operator.EQ, DKQConstant.DEL_NO));
        filters.put("status", new SearchFilter("status", SearchFilter.Operator.EQ, status));
        Specification<GroupRecruit> spec = DynamicSpecifications.bySearchFilter(filters.values(), GroupRecruit.class);
        List<GroupRecruit> list = this.groupRecruitDao.findAll(spec);
        if(null != list && list.size()>0)
            return list.get(list.size()-1);
        return null;
    }

    @Override
    public List<GroupRecruit> findByServiceField(String createTime, String serviceField) throws ServiceRuntimeException
    {
        List<GroupRecruit> result = new ArrayList<GroupRecruit>();
        Sort sort = new Sort(Sort.Direction.DESC, "createTime");

        for(String tag:serviceField.split(";"))
        {
            //Map<String,Object> map = new HashMap<String, Object>();
            //map.put("LIKE_NAME",name);
            //Map<String, SearchFilter> filters = SearchFilter.parse(map);

            Map<String, SearchFilter> filters = Maps.newHashMap();
            filters.put("serviceField", new SearchFilter("serviceField", SearchFilter.Operator.LIKE, tag));
            filters.put("delStatus", new SearchFilter("delStatus", SearchFilter.Operator.EQ, DKQConstant.DEL_NO));
            if(StringUtils.isNotBlank(createTime))
                filters.put("createTime", new SearchFilter("createTime", SearchFilter.Operator.GT, createTime));
            Specification<GroupRecruit> spec = DynamicSpecifications.bySearchFilter(filters.values(), GroupRecruit.class);
            List<GroupRecruit> temp = this.groupRecruitDao.findAll(spec, sort);
            if(null != temp && temp.size()>0)
                result.addAll(temp);
        }
        List<GroupRecruit> listWithoutDup = new ArrayList<GroupRecruit>(new HashSet<GroupRecruit>(result));
        return listWithoutDup;
    }

    @Override
    public Page<GroupRecruit> findAll(String createTime, int pageNumber) throws ServiceRuntimeException
    {
        Sort sort = new Sort(Sort.Direction.DESC, "createTime");
        PageRequest pageRequest = new PageRequest(pageNumber - 1, 20, sort);

        //Map<String,Object> map = new HashMap<String, Object>();
        //map.put("LIKE_NAME",name);
        //Map<String, SearchFilter> filters = SearchFilter.parse(map);

        Map<String, SearchFilter> filters = Maps.newHashMap();
        filters.put("delStatus", new SearchFilter("delStatus", SearchFilter.Operator.EQ, DKQConstant.DEL_NO));
        if(StringUtils.isNotBlank(createTime))
            filters.put("createTime", new SearchFilter("createTime", SearchFilter.Operator.GT, createTime));

        Specification<GroupRecruit> spec = DynamicSpecifications.bySearchFilter(filters.values(), GroupRecruit.class);
        return this.groupRecruitDao.findAll(spec,pageRequest);
    }

    @Override
    public List<GroupRecruit> findTitleLike(String title) throws ServiceRuntimeException
    {
        Map<String, SearchFilter> filters = Maps.newHashMap();
        filters.put("delStatus", new SearchFilter("delStatus", SearchFilter.Operator.EQ, DKQConstant.DEL_NO));
        filters.put("title", new SearchFilter("title", SearchFilter.Operator.LIKE, title));
        Specification<GroupRecruit> spec = DynamicSpecifications.bySearchFilter(filters.values(), GroupRecruit.class);
        return this.groupRecruitDao.findAll(spec);
    }

    @Override
    public List<GroupRecruit> findByJobSkillSerivice(final String tag) throws ServiceRuntimeException
    {
        return this.groupRecruitDao.findAll(new Specification<GroupRecruit>()
        {
            @Override
            public Predicate toPredicate(Root<GroupRecruit> root, CriteriaQuery<?> criteriaQuery, CriteriaBuilder criteriaBuilder)
            {
                Predicate predicate = null;

                //path转化
                List<Predicate> orPredicates = Lists.newArrayList();

                Path<String> _job = root.get("job");
                Path<String> _serviceField = root.get("serviceField");
                Path<String> _skills = root.get("skill");

                orPredicates.add(criteriaBuilder.or(criteriaBuilder.like(_job, tag)));
                orPredicates.add(criteriaBuilder.or(criteriaBuilder.like(_serviceField, tag)));
                orPredicates.add(criteriaBuilder.or(criteriaBuilder.like(_skills, tag)));

                // 将所有条件用 and 联合起来
                if (!orPredicates.isEmpty()) {
                    predicate =  criteriaBuilder.or(orPredicates.toArray(new Predicate[orPredicates.size()]));
                }

                return predicate;
            }
        });
    }

    @Override
    public void updateStatus() throws ServiceRuntimeException
    {
        SimpleDateFormat DefaultTimeFormatter = new SimpleDateFormat("yyyy-MM-dd HH:mm");
        Map<String, SearchFilter> filters = Maps.newHashMap();
        filters.put("status", new SearchFilter("status", SearchFilter.Operator.EQ, DKQConstant.PROCEED_START));
        filters.put("delStatus", new SearchFilter("delStatus", SearchFilter.Operator.EQ, DKQConstant.DEL_NO));
        Specification<GroupRecruit> spec = DynamicSpecifications.bySearchFilter(filters.values(), GroupRecruit.class);
        List<GroupRecruit> list =  this.groupRecruitDao.findAll(spec);
        if(null != list && list.size()>0)
        {
            for(GroupRecruit gr:list)
            {
                try
                {
                    Date today = new Date();
                    SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");
                    Date endDate = sdf.parse(gr.getStopApplyTime());
                    //检查当是否已结束
                    if(today.after(endDate))
                    {
                        gr.setStatus(DKQConstant.PROCEED_END);
                        this.groupRecruitDao.save(gr);
                    }
                } catch (ParseException e)
                {
                    e.printStackTrace();
                }
            }
        }
    }
}
